package com.grain.security.rbac.repository.support;

import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

public abstract class GrainSpecification<T, C> extends AbstractEventConditionBuilder<T, C>
        implements Specification<T> {

    public GrainSpecification(C condition) {
        super(condition);
    }

    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        if (Long.class != query.getResultType()) {
            addFetch(root);
        }
        List<Predicate> predicates = new ArrayList<>();
        QueryWraper<T> queryWraper = new QueryWraper<T>(root, cb, predicates, query);
        addCondition(queryWraper);
        Predicate permissionCondition = getPermissionCondition(queryWraper);
        if (permissionCondition != null) {
            queryWraper.addPredicate(permissionCondition);
        }
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }

    protected Predicate getPermissionCondition(QueryWraper<T> queryWraper) {
        return null;
    }

    protected abstract void addCondition(QueryWraper<T> queryWraper);

    protected void addFetch(Root<T> root) {
    }
}
